/**
 * Copyright (c) 2009-2011, chunquedong(YangJiandong)
 * 
 * This file is part of ChunMap project
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
 * 
 * History:
 *     2010-05-05  Jed Young  Creation
 */
package chunmap.model.algorithm;

import chunmap.model.coord.CoordSeqEditor;
import chunmap.model.coord.Coordinate2D;
import chunmap.model.coord.CoordinateSeq;
import chunmap.model.coord.Position;
import chunmap.model.elem.Angle;
import chunmap.model.elem.LineSegment;
import chunmap.model.elem.Triangle;
import chunmap.model.geom.GeometryException;

public class RingAlgorithm {
	/// <summary>
    /// 点是否包含在环内
    /// </summary>
    /// <param name="point"></param>
    /// <param name="points"></param>
    /// <returns></returns>
    static public boolean containIn(CoordinateSeq points, Position point)
    {
        double arf = 0;
        Position p0 = null;
        for (Position p : points)
        {
            if (p0 == null)
            {
                p0 = p;
            }
            else
            {
                Angle a = new Angle(p0, point, p);
                arf += a.computeAngle();

                p0 = p;
            }
        }
        if (Math.abs(arf) > 6.28) return true;
        else return false;
    }

    static public boolean containLineString(CoordinateSeq points, CoordinateSeq other)
    {
        //打断
        CoordSeqEditor tLine = new CoordSeqEditor(other);
        tLine.tryInsertAll(points);
        // 片段在里面
        for (int i = 0, n = tLine.size() - 1; i < n; i++)
        {
            LineSegment lseg = tLine.getLineSegment(i);
            if (!containIn(points,lseg.getMiddlePoint()))
            {
                return false;
            }
        }
        return true;
    }

    //------------------------------------------------------------------------
    /// <summary>
    /// 是否为顺时针
    /// </summary>
    /// <returns></returns>
    static public boolean clockwise(CoordinateSeq points)
    {
        int i2 = maxPoint(points);
        int i1 = (i2 == 0) ? points.size() - 1 : i2 - 1;
        int i3 = (i2 == (points.size() - 1)) ? 0 : i2 + 1;
        Angle angle = new Angle(points.getCoordinate(i1)
            , points.getCoordinate(i2), points.getCoordinate(i3));

        int i = angle.clockwise();
        if (i == 1)
            return false;
        else if (i == -1)
            return true;
        else
            throw new GeometryException("notSimpleGeometry");
    }
    static private int maxPoint(CoordinateSeq points)
    {
        Position maxP = points.getCoordinate(0);
        int maxI = 0;
        for (int i = 1, n = points.size(); i < n; i++)
        {
            Position p = points.getCoordinate(i);
            if (p.compareTo(maxP) > 0)
            {
                maxP = p;
                maxI = i;
            }
        }
        return maxI;
    }

    //------------------------------------------------------------------------

    static public double computeArea(CoordinateSeq points)
    {
        double area = 0;
        Position p = points.getCoordinate(0);
        for (int i = 1, n = points.size() - 1; i < n; i++)
        {
            Triangle trian = new Triangle(p, points.getCoordinate(i), points.getCoordinate(i + 1));
            area += trian.computeArea();
        }
        return area;
    }
    static public Position computeCenter(CoordinateSeq points)
    {
        double xh = 0;// x的和
        double he = 0;// 权和
        double yh = 0;// y的和
        Position p = points.startPoint();
        for (int i = 1, n = points.size() - 1; i < n; i++)
        {
            Triangle trian = new Triangle(p, points.getCoordinate(i), points.getCoordinate(i + 1));
            Position center = trian.computeCenter();
            double area = trian.computeArea();
            xh += area * center.getX();
            yh += area * center.getY();
            he += area;
        }
        double x = xh / he;
        double y = yh / he;

        return new Coordinate2D(x, y);
    }
}